package com.woniuxy.driverschool.service.courseArrangement;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.woniuxy.driverschool.entity.*;
import com.woniuxy.driverschool.mapper.*;
import com.woniuxy.driverschool.service.courseArrangement.parameterMessage.MessageForInsertIntoSchoolTimeTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author shichen
 * @create 2021-10-08-9:49
 * @description
 */
@Service
public class SelectClassTimeService {

    private static final Log log = LogFactory.get();

    /**
     * 查找具体的时间段
     */
    @Autowired
    PeriodDetailMapper PeriodDetailMapper;

    /**
     * 查找教学方案
     */
    @Autowired
    PeriodMapper PeriodMapper;

    /**
     * 模糊查询教练
     */
    @Autowired
    CoachMapper CoachMapper;

    @Autowired
    StudentMapper studentMapper;

    /**
     * 查找时间安排表
     */
    @Autowired
    SchoolTimeTableMapper schoolTimeTableMapper;

    /**
     * 学生出席表
     */
    @Autowired
    StudentAppointmentMapper studentAppointmentMapper;


    /**
     * 根据主键查询，具体的教学时间，生成表头
     * @param pid
     * @return
     */
    private List<Map<String, String>> SelectClassTimeForTableHeader(int pid) {
        List<PeriodDetail> periodDetails = PeriodDetailMapper.selectPeriodDetailsByPeriodId(pid);
        ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
        for(PeriodDetail p : periodDetails ){

            String start = DateUtil.format(p.getTimeFrom(), "HH:mm");
            String end = DateUtil.format(p.getTimeTo(), "HH:mm");
            String period = start + "-" + end;

            // 和前端的格式规定 ， 这里其实可以有一个适配器，以后可以搞一个数据装换匹配层
            HashMap<String, String> map = MapUtil.newHashMap();
            map.put("dataItem", p.getPeriodDetailId().toString());
            map.put("dataName", period);

            list.add(map);
        }
        log.debug("生成的表头：{}", list);
        return list;
    }

    /**
     * 返回所有的教学方案，是一个 JSON 数组 开放给 controller 调用
     * @return JSONArray
     */
    public JSONArray SelectAllPeriod(){

        List<Period> list = PeriodMapper.selectAllPeriod();

        // JSON 数组
        JSONArray array = JSONUtil.createArray();
        for(Period p : list){
            System.out.println(p);
            String id = p.getPeriodId().toString();
            String periodName = p.getPeriodName();
            // 创建 JSON 对象
            JSONObject json1 = JSONUtil.createObj();
            json1.set("id", id);
            json1.set("periodName", periodName);
            array.add(json1);
        }
        System.out.println(array);

        return array;
    }

    /**
     * 模糊查询教练
     * @param teacherName
     * @return
     */
    private List<Coach> selectTeacher(String teacherName) {
       return  CoachMapper.findCoachesByName(teacherName);
    }


    /**
     * @param subject     选择的科目
     * @param teacherName 教练的名字
     * @param dateStr     日期字符串
     * @param id          选择的排课方案
     * @return 教练的时间安排
     */
    private ArrayList<Map> generateDynamicTable(String subject, String teacherName, String dateStr, String id) {

        List<Coach> coaches = CoachMapper.findCoachesByNameAndSubject(teacherName, subject);

        if (coaches == null) {
            RuntimeException exception = new RuntimeException("找不到教练");
            log.error(exception);
            throw exception;
        }

        Date date = DateUtil.parse(dateStr, "yyyy-MM-dd");
        // 用来调整时间 ，Spring中 yml 设置时区失败，所以在这里手动调整
        DateTime newDate = DateUtil.offsetDay(date, 1);

        ArrayList<Map> messageForSelectLessenIsFreeArrayList = new ArrayList<>();
        for (Coach coach : coaches) {

            Map message = selectLessonByCoachAndDate(coach, newDate, id);
            messageForSelectLessenIsFreeArrayList.add(message);
            log.debug("查出来的教练{}，时间情况：{}", coach, message);
        }


        return messageForSelectLessenIsFreeArrayList;
    }

    /**
     * 根据老师和日期来排查他的档期，如果没查到就说明档期是空的
     * @param coach
     * @param date
     * @param id 排课方案的id
     */
    private Map selectLessonByCoachAndDate(Coach coach, Date date, String id) {
        SchoolTimeTable schoolTimeTable = new SchoolTimeTable();
        schoolTimeTable.setCoach(coach);
        schoolTimeTable.setTdate(date.toString());
        //查教案对应的时间段
        List<PeriodDetail> periodDetailList = PeriodDetailMapper.selectPeriodDetailsByPeriodId(Integer.parseInt(id));
        //查教练和具体日期对应的档期
        List<SchoolTimeTable> timeTableList = schoolTimeTableMapper.selectLessonByCondition(schoolTimeTable);

        HashMap map = new HashMap<String,String>(15);
        map.put("coachId", coach.getCoachId());
        map.put("coachName", coach.getCoachName());
        map.put("license",coach.getDriverNum());
        map.put("date", DateUtil.format(date, "yyyy/MM/dd"));

        if (timeTableList!=null){
            // 检查检索算法可以优化。。。
            // 这里默认一般是 15 个时间段，也就是一天 15 节课
            for (PeriodDetail periodDetail : periodDetailList) {

                // 生成<key,value>数据的key 与前端对应的数据
                String period = periodDetail.getPeriodDetailId().toString();
                map.put(period, "未排课");

                if (timeTableList.size() > 0) {
                    for (SchoolTimeTable timeTable : timeTableList) {
                        PeriodDetail interval = timeTable.getInterval();

                        // 如果查询到则证明已经放过课程了
                        if (interval.getPeriodDetailId().equals(periodDetail.getPeriodDetailId())) {

                            map.put(period, "已经排课");
                            // 否则则是没有排课
                        }
//                        else {        这里写错了
//                            //map.put(period, "未排课");
//                        }
                    }
                    // 则全部都没排课
                }
            }

        }

        return map;

    }


    /**
     * 准备响应给客户端的消息，Controller 调用它
     *
     * @param subject
     * @param teacherName
     * @param dateStr
     * @param id
     * @return
     */
    public Map<String, Object> getMessage(String subject, String teacherName, String dateStr, String id) {
        ArrayList<Map> messageForSelectLessenIsFrees = generateDynamicTable(subject, teacherName, dateStr, id);
        List<Map<String, String>> tableHeadStr = SelectClassTimeForTableHeader(Integer.parseInt(id));

        /*// 把得到的时间数据转为 JSON 串
        String jsonStr = JSONUtil.toJsonStr(tableHeadStr);*/

        //把查询到的数据放置在 map 中
        Map<String, Object> map = MapUtil.newHashMap();
        map.put("teachers", messageForSelectLessenIsFrees);
        map.put("classTimes", tableHeadStr);

        log.debug("发送给客户端的消息：{}", map);
        return map;
    }

    /**
     * 向数据库中插入条目，代表排课,这里是一条一条的排课
     *
     * @param subject 选择的科目
     * @param teacherid 选择的老师
     * @param dateStr 选择的日期
     * @param id 选择的 periodDetailId
     */
    public void setLesson(String subject, String teacherid, String dateStr, String id) {

        //进行插入前先判断
        List<SchoolTimeTable> schoolTimeTables = schoolTimeTableMapper.selectLessonByCondition(new SchoolTimeTable().
                setCoach(new Coach().setCoachId(Integer.parseInt(teacherid))).
                setTdate(dateStr).
                setInterval(new PeriodDetail().setPeriodDetailId(Integer.parseInt(id))));

        // 查不到才插入数据
        if(schoolTimeTables.size()==0){
            MessageForInsertIntoSchoolTimeTable message = new MessageForInsertIntoSchoolTimeTable((Integer.parseInt(teacherid)), dateStr, Integer.parseInt(id));
            schoolTimeTableMapper.insertLesson(message);
            log.debug("向数据库表schoolTimeTable插入：{}"+message);
        }else {
           throw new RuntimeException("已经有数据了");
        }



    }
    public void removeLesson(String subject, String teacherid, String dateStr, String id) {

//        //进行插入前先判断
//        List<SchoolTimeTable> schoolTimeTables = schoolTimeTableMapper.selectLessonByCondition(new SchoolTimeTable().
//                setCoach(new Coach().setCoachId(Integer.parseInt(teacherid))).
//                setTdate(dateStr).
//                setInterval(new PeriodDetail().setPeriodDetailId(Integer.parseInt(id))));
//
//        // 查不到才插入数据
//        if(schoolTimeTables.size()==0){
//            MessageForInsertIntoSchoolTimeTable message = new MessageForInsertIntoSchoolTimeTable((Integer.parseInt(teacherid)), dateStr, Integer.parseInt(id));
//            schoolTimeTableMapper.insertLesson(message);
//            log.debug("向数据库表schoolTimeTable插入：{}"+message);
//        }else {
//            throw new RuntimeException("已经有数据了");
//        }
        MessageForInsertIntoSchoolTimeTable message = new MessageForInsertIntoSchoolTimeTable((Integer.parseInt(teacherid)), dateStr, Integer.parseInt(id));
        schoolTimeTableMapper.deleteLesson(message);
    }
    public ArrayList<Map> SelectLesson4Stu(String subject, String teacherName, Date date, String id) {


        List<Coach> coachesByNameAndSubject = CoachMapper.findCoachesByNameAndSubject(teacherName, subject);
        ArrayList<Map> List = new ArrayList<>();

        for (Coach coach : coachesByNameAndSubject) {
            Map map = selectLesson4Student(coach, date, id);
            List.add(map);
        }
        return List;
    }

    /**
     * 添加上课人数只能 一个一个的添加
     * @param tid schooltimetable的主键
     * @param sid 学生的主键
     * @param subject 选择的科目

     */
    public void addAttendance(int tid, int sid, int subject, String coachName) {

        SchoolTimeTable schoolTimeTable = schoolTimeTableMapper.selectLessonByID(tid);
        Student student = studentMapper.selectStudentBySid(sid);
        AppointLessonMessage appointLessonMessage=new AppointLessonMessage();
        appointLessonMessage.setStudent(student);
        appointLessonMessage.setCoachName(coachName);
        appointLessonMessage.setSubject(subject);
        appointLessonMessage.setAppDate(DateUtil.parse(schoolTimeTable.getTdate()));
        appointLessonMessage.setPeriodDetail(schoolTimeTable.getInterval());
        appointLessonMessage.setSaTime(new Date());
        appointLessonMessage.setSaState(1);
        if(student.getPackageName().contains("会员班")){
            if(schoolTimeTable.getTnumber()==0){
             studentAppointmentMapper.insertLesson(appointLessonMessage);
             schoolTimeTableMapper.modifyNumber(4, tid);
            }else{
                throw new RuntimeException("已有人预约，会员不能再进行预约");
            }
        }else{
            if(schoolTimeTable.getTnumber()<4){
             studentAppointmentMapper.insertLesson(appointLessonMessage);
             schoolTimeTableMapper.modifyNumber(schoolTimeTable.getTnumber()+1,tid);
            }

        }

    }

    private Map selectLesson4Student(Coach coach, Date date, String id) {

        SchoolTimeTable schoolTimeTable = new SchoolTimeTable();
        schoolTimeTable.setCoach(coach);
        schoolTimeTable.setTdate(date.toString());
        //查教案对应的时间段
        List<PeriodDetail> periodDetailList = PeriodDetailMapper.selectPeriodDetailsByPeriodId(Integer.parseInt(id));
        //查教练和具体日期对应的档期
        List<SchoolTimeTable> timeTableList = schoolTimeTableMapper.selectLessonByCondition(schoolTimeTable);

        HashMap map = new HashMap<String, String>(15);
        map.put("coachId", coach.getCoachId());
        map.put("coachName", coach.getCoachName());
        map.put("license", coach.getDriverNum());
        map.put("date", DateUtil.format(date, "yyyy/MM/dd"));

        if (timeTableList != null) {
            // 检查检索算法可以优化。。。
            // 这里默认一般是 15 个时间段，也就是一天 15 节课
            for (PeriodDetail periodDetail : periodDetailList) {

                // 生成<key,value>数据的key 与前端对应的数据
                String period = periodDetail.getPeriodDetailId().toString();
                map.put(period, "未排课");
                if (timeTableList.size() > 0) {
                    for (SchoolTimeTable timeTable : timeTableList) {
                        PeriodDetail interval = timeTable.getInterval();

                        // 如果查询到则证明已经放过课程了
                        if (interval.getPeriodDetailId().equals(periodDetail.getPeriodDetailId())) {
                            if(timeTable.getTnumber()<4){
                                map.put(period, timeTable.getTnumber().toString());
                                map.put(period+"t",timeTable.getTid());
                            }else if(timeTable.getTnumber()==4){
                                map.put(period, "已约满");

                            }

                        }

                    }
                }
            }

        }

        return map;

    }

    /**
     * 开放给学生选课
     * @param subject
     * @param teacherName
     * @param date
     * @param id
     * @return
     */
    public Map<String, Object> getMessage4Stu(String subject, String teacherName, Date date, String id){

        ArrayList<Map> messageForSelectLessenIsFrees = SelectLesson4Stu(subject, teacherName, date, id);
        List<Map<String, String>> tableHeadStr = SelectClassTimeForTableHeader(Integer.parseInt(id));


        //把查询到的数据放置在 map 中
        Map<String, Object> map = MapUtil.newHashMap();
        map.put("teachers", messageForSelectLessenIsFrees);
        map.put("classTimes", tableHeadStr);

        log.debug("发送给客户端的消息：{}", map);
        return map;
    }
}
